/*
 * 代号：凤凰
 * http://www.jphenix.org
 * 2022年9月1日
 * V4.0
 */
package com.jphenix.webserver.api;

import java.io.File;
import java.io.InputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
import java.util.EventListener;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Set;

import com.jphenix.servlet.exception.ServletException;
import com.jphenix.share.lang.SEnumeration;
import com.jphenix.standard.docs.ClassInfo;
import com.jphenix.standard.servlet.api.IServletContext;
import com.jphenix.standard.servlet.api.ISessionCookieConfig;
import com.jphenix.webserver.instancea.Identification;
import com.jphenix.webserver.instancea.Serve;
import com.jphenix.webserver.instancea.ServeParameter;

/**
 * Servlet上下文
 * 
 * 2022-09-04 重构了内置Servlet容器，不依赖外部ServletApi包
 * 
 * @author MBG
 * 2022年9月1日
 */
@ClassInfo({"2022-09-04 21:58","Servlet上下文"})
public class ServletContextImpl implements IServletContext {

	private Serve          kernel             = null;    // 核心类实例
	private ServeParameter param              = null;    // 服务配置信息类
	private String         requestEncoding    = "UTF-8"; // 请求编码格式
	private String         responseEncoding   = "UTF-8"; // 反馈编码格式
	
	private Hashtable<String,Object> attributes = new Hashtable<String,Object>(); // 上下文属性容器
	
	private final String SERVLET_CONTEXT_NAME = "native_servlet"; // 默认名称
	
	/**
	 * 构造函数
	 * @author MBG
	 */
	public ServletContextImpl(Serve servletContext) {
		super();
		this.kernel = servletContext;
	}
	
	/**
	 * 获取服务配置信息类
	 * @return 服务配置信息类
	 * 2022年9月3日
	 * @author MBG
	 */
	private ServeParameter getServeParameter() {
		if(param==null) {
			param = kernel.getServeParameter();
		}
		return param;
	}

	@Override
	public String getTempDir() {
		return "native.webserver.servlet.context.tempdir";
	}

	@Override
	public String getOrderedLibs() {
		return "native.webserver.servlet.context.orderedLibs";
	}

	@Override
	public String getContextPath() {
		return getServeParameter().getContextPath();
	}

	@Override
	public IServletContext getContext(String uripath) {
		return this;
	}

	@Override
	public int getMajorVersion() {
		return Identification.MAJOR_VERSION;
	}

	@Override
	public int getMinorVersion() {
		return Identification.MINOR_VERSION;
	}

	@Override
	public int getEffectiveMajorVersion() {
		return Identification.MAJOR_VERSION;
	}

	@Override
	public int getEffectiveMinorVersion() {
		return Identification.MINOR_VERSION;
	}

	@Override
	public String getMimeType(String file) {
		return getServeParameter().getMimeType(file);
	}

	@Override
	public Set<String> getResourcePaths(String path) {
		String realPath = getRealPath(path);
		if (realPath != null) {
			String[] dir = new File(realPath).list();
			if (dir.length > 0) {
				HashSet<String> set = new HashSet<String>(dir.length);
				for (int i = 0; i < dir.length; i++) {
                    set.add(dir[i]);
                }
				return set;
			}
		}
		return null;
	}

	@Override
	public URL getResource(String path) throws MalformedURLException {
		if (path == null || path.length() == 0 || path.charAt(0) != '/') {
            throw new MalformedURLException("Path " + path + " is not in acceptable form.");
        }
		return new URL("file", "localhost", getRealPath(path));
	}

	@Override
	public InputStream getResourceAsStream(String path) {
		try {
			return getResource(path).openStream();
		} catch (Exception e) {
		}
		return null;
	}

	@Override
	public void log(String msg) {
		kernel.log(msg);
	}

	@Override
	public void log(String message, Throwable throwable) {
		kernel.log(message,throwable);
	}

	@Override
	public String getRealPath(String path) {
		if (path==null) {
			path = "";
		}
		if (kernel.getServeParameter().getContextPathLength()>0 && path.startsWith(getContextPath())) {
			path = path.substring(getServeParameter().getContextPathLength());
		}
		return getServeParameter().getRealPath(path);
	}

	@Override
	public String getServerInfo() {
		return Identification.SERVER_NAME + " " + Identification.SERVER_VERSION + " ("
				+ Identification.SERVER_URL + ")";
	}

	@Override
	public String getInitParameter(String key) {
		return getServeParameter().getPropertyMap().get(key);
	}

	@SuppressWarnings({ "unchecked", "rawtypes" })
	@Override
	public Enumeration<String> getInitParameterNames() {
		return new SEnumeration(getServeParameter().getPropertyMap().keySet().iterator());
	}

	@Override
	public boolean setInitParameter(String key, String value) {
		getServeParameter().getPropertyMap().put(key,value);
		return true;
	}

	@Override
	public Object getAttribute(String key) {
		return attributes.get(key);
	}

	@Override
	public Enumeration<String> getAttributeNames() {
		return attributes.keys();
	}

	@Override
	public void setAttribute(String key, Object value) {
		if(value==null) {
			attributes.remove(key);
		}else {
			attributes.put(key,value);
		}
	}

	@Override
	public void removeAttribute(String key) {
		attributes.remove(key);
	}

	@Override
	public String getServletContextName() {
		return SERVLET_CONTEXT_NAME;
	}

	@Override
	public ISessionCookieConfig getSessionCookieConfig() {
		return null;
	}

	@Override
	public void addListener(String className) {}

	@Override
	public <T extends EventListener> void addListener(T t) {}

	@Override
	public void addListener(Class<? extends EventListener> listenerClass) {}

	@Override
	public <T extends EventListener> T createListener(Class<T> listenerClass) throws ServletException {
		return null;
	}

	@Override
	public ClassLoader getClassLoader() {
		return kernel.getClass().getClassLoader();
	}

	@Override
	public String getVirtualServerName() {
		return null;
	}

	@Override
	public int getSessionTimeout() {
		return getServeParameter().getSessionTimeOut();
	}

	@Override
	public void setSessionTimeout(int sessionTimeout) {
		getServeParameter().setSessionTimeout(sessionTimeout);
	}

	@Override
	public String getRequestCharacterEncoding() {
		return requestEncoding;
	}

	@Override
	public void setRequestCharacterEncoding(String encoding) {
		if(encoding==null) {
			return;
		}
		this.requestEncoding = encoding;
	}

	@Override
	public String getResponseCharacterEncoding() {
		return responseEncoding;
	}

	@Override
	public void setResponseCharacterEncoding(String encoding) {
		if(encoding==null) {
			return;
		}
		this.responseEncoding = encoding;
	}
}
